# ============================================================================ #
# Makefile для проекта lib_state (квантовое преобразование на openmp,mpi,shmem)#
#                                                                              #
# !!!!!!!!!!!!!!!!!!!!!!! ВАЖНО !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #
#                                                                              #
#   При первом запуске выйдет ОШИБКА при линковке в окончательный модуль!      #
#   Это особенность данной версии Makefile. просто соберите проект еще раз!    #
#                                                                              #
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #
#                                                                              #
#  если интересно в чем ошибка:                                                #
# дело в том, что откомпилированные объектные файлы сохраняются не корневой    #
# каталог, а в папку obj, но утилита make (видимо ее особенность) запоминает   #
# отсутствие файлов в корневом каталоге и потом ищет их только там (хотя опция #
# vpath %.o $(OBJ_NOW) стоит задолго до этого). В будущем исправлю             #
#                                                                              #
# ============================================================================ #


# определение имени программы
PROG1 = state_openmp
PROG2 = state_mpi
PROG3 = state_shmem

# директории
INCLUDE_DIR = include/ /opt/dislib
SRC_DIR     = src/
LIB_DIR     =

# библиотеки
LIBMODULES :=

# компиляторы
CC            = mpicxx
CFLAGSADD     = -shared
CFLAGSOPENMP  = -DUSE_OPENMP -openmp
CFLAGSMPI     = -DUSE_MPI
CFLAGSSHMEM   = -DUSE_SHMEM


BIN         = bin/
BIN_DEBUG   = $(BIN)/debug/
BIN_RELEASE = $(BIN)/release/
BIN_NOW     = $(BIN_DEBUG)/

OBJ         = obj/
OBJ_DEBUG   = $(OBJ)/debug/
OBJ_RELEASE = $(OBJ)/release/
#OBJ_NOW     = $(OBJ_DEBUG)/

OBJ_DEBUG_OPENMP   = $(OBJ_DEBUG)/openmp/
OBJ_RELEASE_OPENMP = $(OBJ_RELEASE)/openmp/
OBJ_DEBUG_MPI      = $(OBJ_DEBUG)/mpi/
OBJ_RELEASE_MPI    = $(OBJ_RELEASE)/mpi/
OBJ_DEBUG_SHMEM    = $(OBJ_DEBUG)/shmem/
OBJ_RELEASE_SHMEM  = $(OBJ_RELEASE)/shmem/

OBJ_NOW_OPENMP = $(OBJ_DEBUG_OPENMP)
OBJ_NOW_MPI    = $(OBJ_DEBUG_MPI)
OBJ_NOW_SHMEM  = $(OBJ_DEBUG_SHMEM)

# =============================================================================
WORK_DIR    = `pwd`
DATE        = `date +%X`

# определение всех имен через директории
SRCMODULES := $(notdir $(wildcard  $(SRC_DIR)/*.cpp))
OBJMODULES := $(SRCMODULES:.cpp=.o)
INCMODULES := $(notdir $(wildcard $(INCLUDE_DIR)/*.h) )

#некоторые автоматические опции
CFLAGSDEBUG   = -g -Wall -pedantic
CFLAGSRELEASE = 
CFLAGSINCLUDE = $(addprefix -I, $(INCLUDE_DIR))
CFLAGSLIB     = $(addprefix -L, $(LIB_DIR)) $(addprefix -l, $(LIBMODULES))
CFLAGS        = $(CFLAGSDEBUG) $(CFLAGSINCLUDE) $(CFLAGSLIB) $(CFLAGSADD)
# =============================================================================

# абстрактные цели
.PHONY: all print clean openmp mpi shmem rebuild

# пути поиска шаблонов
vpath %.h   $(INCLUDE_DIR)
vpath %.cpp $(SRC_DIR)
#vpath %.o   $(OBJ_NOW)

# главная цель 
all: mpi

openmp:  $(OBJMODULES)
	$(CC) $(CFLAGS) $(CFLAGSOPENMP) $(addprefix $(OBJ_NOW_OPENMP),$^) -o $(BIN_NOW)/lib$(PROG1).so
	cp $(BIN_NOW)/lib$(PROG1).so .
mpi:  $(OBJMODULES)
	$(CC) $(CFLAGS) $(CFLAGSMPI)  $(addprefix $(OBJ_NOW_MPI),$^) -o $(BIN_NOW)/lib$(PROG2).so
	cp $(BIN_NOW)/lib$(PROG2).so .
shmem:  $(OBJMODULES)
	$(CC) $(CFLAGS) $(CFLAGSSHMEM) $(addprefix $(OBJ_NOW_SHMEM),$^) -o $(BIN_NOW)/lib$(PROG3).so
	cp $(BIN_NOW)/lib$(PROG3).so .

rebuild: clean build

# отладочная печать 
print:
	@echo "Choose openmp, mpi or shmem"

ifeq (openmp, $(MAKECMDGOALS))
CFLAGSGOAL = $(CFLAGSOPENMP)
OBJ_NOW = $(OBJ_NOW_OPENMP)
endif

ifeq (mpi, $(MAKECMDGOALS))
CFLAGSGOAL = $(CFLAGSMPI)
OBJ_NOW = $(OBJ_NOW_MPI)
endif

ifeq (shmem, $(MAKECMDGOALS))
CFLAGSGOAL = $(CFLAGSSHMEM)
OBJ_NOW = $(OBJ_NOW_SHMEM)
endif

# шаблоны компилирования 
%.o: %.cpp %.h
	$(CC) $(CFLAGS) $(CFLAGSGOAL) -c -fPIC $< -o $(OBJ_NOW)/$@

%.o: %.cpp
	$(CC) $(CFLAGS) $(CFLAGSGOAL) -c -fPIC $< -o $(OBJ_NOW)/$@

# включение файла зависимостей
ifneq (clean, $(MAKECMDGOALS))
-include deps.mk
endif

# файл зависимостей
deps.mk: $(SRCMODULES)
	$(CC) $(CFLAGSINCLUDE) -MM $^ > $@

# очистка
clean:
	rm -f deps.mk
	rm -f $(OBJ_NOW_OPENMP)/*.o
	rm -f $(OBJ_NOW_MPI)/*.o
	rm -f $(OBJ_NOW_SHMEM)/*.o
	rm -f $(BIN_NOW)/lib$(PROG1).so
	rm -f $(BIN_NOW)/lib$(PROG2).so
	rm -f $(BIN_NOW)/lib$(PROG3).so
	rm -f lib$(PROG1).so
	rm -f lib$(PROG2).so
	rm -f lib$(PROG3).so
